package com.ruoyi.system.service.impl;


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.druid.pool.DruidDataSource;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.SysDatasource;
import com.ruoyi.system.mapper.SysDatasourceMapper;
import com.ruoyi.system.service.ISysDatasourceService;

import com.ruoyi.common.datasource.DynamicDataSource;
/**
 * 数据源配置Service业务层实现
 * 
 * @author ruoyi
 */
@Service
public class SysDatasourceServiceImpl implements ISysDatasourceService
{
    private static final Logger log = LoggerFactory.getLogger(SysDatasourceServiceImpl.class);

    @Autowired
    private SysDatasourceMapper datasourceMapper;

    /**
     * 查询数据源配置
     */
    @Override
    public SysDatasource selectDatasourceById(Long datasourceId)
    {
        return datasourceMapper.selectDatasourceById(datasourceId);
    }

    /**
     * 根据数据源编码查询数据源配置
     */
    @Override
    public SysDatasource selectDatasourceByCode(String datasourceCode)
    {
        return datasourceMapper.selectDatasourceByCode(datasourceCode);
    }

    /**
     * 查询数据源配置列表
     */
    @Override
    public List<SysDatasource> selectDatasourceList(SysDatasource datasource)
    {
        return datasourceMapper.selectDatasourceList(datasource);
    }

    /**
     * 新增数据源配置
     */
    @Override
    public int insertDatasource(SysDatasource datasource)
    {
        // 测试数据源连接是否可用
        if (!testDatasourceConnection(datasource))
        {
            throw new ServiceException("数据源连接失败，请检查配置信息");
        }
        return datasourceMapper.insertDatasource(datasource);
    }

    /**
     * 修改数据源配置
     */
    @Override
    public int updateDatasource(SysDatasource datasource)
    {
        // 测试数据源连接是否可用
        if (!testDatasourceConnection(datasource))
        {
            throw new ServiceException("数据源连接失败，请检查配置信息");
        }
        // 如果数据源状态发生变化，需要刷新动态数据源
        SysDatasource oldDatasource = datasourceMapper.selectDatasourceById(datasource.getDatasourceId());
        int result = datasourceMapper.updateDatasource(datasource);
        if (result > 0 && !StringUtils.equals(oldDatasource.getStatus(), datasource.getStatus()))
        {
            refreshDynamicDatasource();
        }
        return result;
    }

    /**
     * 批量删除数据源配置
     */
    @Override
    public int deleteDatasourceByIds(Long[] datasourceIds)
    {
        int result = datasourceMapper.deleteDatasourceByIds(datasourceIds);
        if (result > 0)
        {
            refreshDynamicDatasource();
        }
        return result;
    }

    /**
     * 删除数据源配置信息
     */
    @Override
    public int deleteDatasourceById(Long datasourceId)
    {
        int result = datasourceMapper.deleteDatasourceById(datasourceId);
        if (result > 0)
        {
            refreshDynamicDatasource();
        }
        return result;
    }

    /**
     * 校验数据源编码是否唯一
     */
    @Override
    public String checkDatasourceCodeUnique(SysDatasource datasource)
    {
        Long datasourceId = StringUtils.isNull(datasource.getDatasourceId()) ? -1L : datasource.getDatasourceId();
        SysDatasource info = datasourceMapper.checkDatasourceCodeUnique(datasource.getDatasourceCode());
        if (StringUtils.isNotNull(info) && info.getDatasourceId().longValue() != datasourceId.longValue())
        {
            return Constants.NOT_UNIQUE;
        }
        return Constants.UNIQUE;
    }

    /**
     * 测试数据源连接
     */
    @Override
    public boolean testDatasourceConnection(SysDatasource datasource)
    {
        Connection conn = null;
        try
        {
            Class.forName(datasource.getDriverClassName());
            conn = DriverManager.getConnection(datasource.getUrl(), datasource.getUsername(), datasource.getPassword());
            return true;
        }
        catch (Exception e)
        {
            log.error("数据源连接测试失败: {}", e.getMessage());
            return false;
        }
        finally
        {
            if (conn != null)
            {
                try
                {
                    conn.close();
                }
                catch (SQLException e)
                {
                    log.error("关闭数据库连接失败", e);
                }
            }
        }
    }

    /**
     * 初始化数据源连接池
     */
    @Override
    public DataSource initDataSource(SysDatasource datasource)
    {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(datasource.getUrl());
        druidDataSource.setUsername(datasource.getUsername());
        druidDataSource.setPassword(datasource.getPassword());
        druidDataSource.setDriverClassName(datasource.getDriverClassName());
        
        // 设置连接池参数
        if (datasource.getInitialSize() != null)
        {
            druidDataSource.setInitialSize(datasource.getInitialSize());
        }
        if (datasource.getMinIdle() != null)
        {
            druidDataSource.setMinIdle(datasource.getMinIdle());
        }
        if (datasource.getMaxActive() != null)
        {
            druidDataSource.setMaxActive(datasource.getMaxActive());
        }
        if (datasource.getMaxWait() != null)
        {
            druidDataSource.setMaxWait(datasource.getMaxWait());
        }
        
        // 设置测试连接参数
        druidDataSource.setValidationQuery("SELECT 1");
        druidDataSource.setTestWhileIdle(true);
        druidDataSource.setTestOnBorrow(false);
        druidDataSource.setTestOnReturn(false);
        
        return druidDataSource;
    }

    /**
     * 刷新动态数据源
     */
    @Override
    public boolean refreshDynamicDatasource()
    {
        try
        {
            DynamicDataSource dynamicDataSource = SpringUtils.getBean(DynamicDataSource.class);
            // 清除现有的数据源
            dynamicDataSource.clearDataSource();
            
            // 重新加载启用的数据源
            List<SysDatasource> enabledDatasources = selectEnabledDatasource();
            for (SysDatasource datasource : enabledDatasources)
            {
                DataSource dataSource = initDataSource(datasource);
                dynamicDataSource.addDataSource(datasource.getDatasourceCode(), dataSource);
            }
            
            log.info("动态数据源刷新成功，加载数据源数量：{}", enabledDatasources.size());
            return true;
        }
        catch (Exception e)
        {
            log.error("刷新动态数据源失败", e);
            return false;
        }
    }

    /**
     * 查询所有启用的数据源
     */
    @Override
    public List<SysDatasource> selectEnabledDatasource()
    {
        return datasourceMapper.selectEnabledDatasource();
    }

    /**
     * 获取数据源状态信息
     */
    @Override
    public Map<String, Object> getDatasourceStatus(String datasourceCode)
    {
        Map<String, Object> statusMap = new HashMap<>();
        try
        {
            DynamicDataSource dynamicDataSource = SpringUtils.getBean(DynamicDataSource.class);
            DataSource dataSource = dynamicDataSource.getDataSource(datasourceCode);
            
            if (dataSource instanceof DruidDataSource)
            {
                DruidDataSource druidDataSource = (DruidDataSource) dataSource;
                statusMap.put("activeCount", druidDataSource.getActiveCount());
                statusMap.put("poolingCount", druidDataSource.getPoolingCount());
                statusMap.put("maxActive", druidDataSource.getMaxActive());
                statusMap.put("initialSize", druidDataSource.getInitialSize());
                statusMap.put("minIdle", druidDataSource.getMinIdle());
                statusMap.put("maxWait", druidDataSource.getMaxWait());
                statusMap.put("waitThreadCount", druidDataSource.getWaitThreadCount());
                statusMap.put("connectErrorCount", druidDataSource.getConnectErrorCount());
                statusMap.put("state", "正常");
            }
            else
            {
                statusMap.put("state", "未知");
            }
        }
        catch (Exception e)
        {
            statusMap.put("state", "异常");
            statusMap.put("errorMsg", e.getMessage());
            log.error("获取数据源状态失败", e);
        }
        return statusMap;
    }
}